/*
编写 : Hexh
时间 : 2012-7-9 10:48:31
*/
using System.Collections.Generic;
using HMIS.FrameWork;
using HMIS.FrameWork.DomainBase;
using HMIS.FrameWork.Repository.Nhb;
using HMIS.Infrastructure.Core.Repositories.Impl;
using Iesi.Collections.Generic;
using HMIS.Infrastructure.Core.Entities;

namespace FsCarInfo.Core.Entity.IRespositories.Impl
{
	/// <summary>
	///	 the repository of FsGatelog
	/// </summary>
	public class FsGatelogRepositoryImpl : RepositoryNhbImpl<FsGatelog>, IFsGatelogRepository
	{

		/// <summary>
		/// 通行记录与道闸信息返回道闸控制标志
		/// </summary>
		/// <param name="gateInfo"></param>
		/// <param name="gateLog"></param>
		/// <returns></returns>
		private string GetIoControlFlag(FsGateinfo gateInfo, FsGatelog gateLog)
		{
			if (!string.IsNullOrEmpty(gateLog.IoControlFlag))
				return gateLog.IoControlFlag; //返回已有的值

			string ioflag = "IO"; //I表示可进，O表示可出

			// 先根据最近的一条通行记录判断闸机出入控制
			if (gateLog.LatestGateLog != null)
			{
				// 判断ID卡当前区域与闸机关系
				if (gateInfo.InAreaId == gateLog.LatestGateLog.InAreaId)
					ioflag = "O";
				else if (gateInfo.OutAreaId == gateLog.LatestGateLog.InAreaId)
					ioflag = "I";
				else
					//当前区域与闸机无关
					throw new ValidationException("ID卡使用异常!该卡车辆当前所在区域应为[" + gateLog.LatestGateLog.InArea.Name + "],与闸机无关,请去财务处重置该卡!");
			}
			
			//判断ID卡是否有未授权记录 判断是否可以离开
			if (ioflag.IndexOf('O') >= 0)
			{
				if (gateLog.UnApprLogList != null)
				{
					if (gateLog.UnApprLogList.Count > 0)
					{
						throw new ValidationException("该车辆有未经财务授权的通行记录。不可离场。");
					}
				}
			}

			return ioflag;
		}

		/// <summary>
		/// 判断是否已经有重复值
		/// </summary>
		/// <param name="fieldName">行名</param>
		/// <param name="fieldValue">值</param>
		/// <param name="id">ID列的值</param>
		/// <returns>True， False</returns>
		public bool IsFieldExist(string fieldName, string fieldValue, string id)
		{
			return base.IsFieldExist(fieldName, fieldValue, id, null);
		}

		// <summary>
		/// 判断是否已经有重复值
		/// </summary>
		/// <param name="fieldName">行名</param>
		/// <param name="fieldValue">值</param>
		/// <param name="id">ID列的值</param>
		/// <param name="where">Where 条件</param>
		/// <returns>True， False</returns>
		public bool IsFieldExistWhere(string fieldName, string fieldValue, string id, string where)
		{
			return base.IsFieldExist(fieldName, fieldValue, id, where);
		}

		/// <summary>
		/// 查询 FsGatelog
		/// </summary>
		/// <param name="query">查询条件</param>
		/// <param name="start">分页开始</param>
		/// <param name="limit">分页大小</param>
		/// <param name="sort">排序条件</param>
		/// <param name="dir">排序方向</param>
		/// <param name="filters">筛选条件</param>
		/// <param name="total">返回记录条数</param>
		/// <returns>返回记录集</returns>
		public IList<FsGatelog> GetPlist(string query, int start, int limit, string sort, string dir, List<DataFilter> filters, out long total)
		{
			// filter
			var strFilter = base.GetHqlstrByExtFilter(filters, "t");

			// todo : 修改查询条件ID1 ID2
			string strQuery = string.IsNullOrEmpty(query) ? strFilter
				: "( t.ID1 = :query or t.ID2 = :query ) "
					+ (string.IsNullOrEmpty(strFilter) ? string.Empty : " and " + strFilter);

			// sort
			string strSort = string.IsNullOrEmpty(sort) ? string.Empty : " order by t." + sort + " " + dir;

			// todo : 修改关联查询条件 OuterColumn
			string strSql = @" from FsGatelog as t 
									left join fetch t.OuterColumn "
				+ (string.IsNullOrEmpty(strQuery) ? string.Empty : " where " + strQuery);

			// 查询
			var selQuery = Session.CreateQuery(@"select t " + strSql + strSort);
			var totQuery = Session.CreateQuery(@"select count(*) " + strSql.Replace(" join fetch ", " join "));

			// 设置查询条件
			if (!string.IsNullOrEmpty(query))
			{
				selQuery.SetString("query", query);
				totQuery.SetString("query", query);
			}

			// 分页
			if (limit > 0)
				selQuery.SetFirstResult(start).SetMaxResults(limit);

			// 汇总并返回
			total = totQuery.UniqueResult<long>();
			return selQuery.List<FsGatelog>();
		}

		/// <summary>
		/// 根据ID卡返回最新的通行控制记录
		/// </summary>
		/// <param name="CardUid"></param>
		/// <returns></returns>
		public FsGatelog GetLatestLogByIdCard(string CardUid, string GateId)
		{
			// 读取ID卡信息
			InfraIdcard idCardInfo = new InfraIdcardRepositoryImpl().GetByCardUId(CardUid);
			if (idCardInfo == null)
			{
				throw new ValidationException("未知的ID卡信息.");
			}

			// 读取当前道闸信息
			FsGateinfo gateInfo = new FsGateinfoRepositoryImpl().Get(GateId);
			if (gateInfo == null)
			{
				throw new ValidationException("未知的道闸信息.");
			}

			// 查找场内的记录
			string strSql = @"select t from FsGatelog as t where t.State = '0' and t.CardUid = :CardUid";
			FsGatelog gateLog = Session.CreateQuery(strSql).
				SetString("CardUid", CardUid).UniqueResult<FsGatelog>();

			// 如果没有记录
			if (gateLog == null)
			{
				// 商品车 公务车
				if (idCardInfo.Type == InfraIdcardType.OffiCarCard)
				{
					throw new ValidationException("商品车/公务车未经审批。不可通过。");
				}
				// 其他车辆创建一条新的记录
				gateLog = new FsGatelog
				{
					//CardUid = CardUid,
					State = "0", //入场标志
					EntTime = System.DateTime.Now,
					InfraIdcard = idCardInfo,
					Type = idCardInfo.Type,
					GateLogList = new HashedSet<FsGatelogList>()
				};
			}

			// 判断与当前道闸的进出关系
			gateLog.IoControlFlag = this.GetIoControlFlag(gateInfo, gateLog);

			return gateLog;
		}

		/// <summary>
		/// 根据ID卡返回当前活动的通行控制记录
		/// </summary>
		/// <param name="CardUid"></param>
		/// <returns></returns>
		public FsGatelog GetCurrentLogByIdCard(string CardUid)
		{
			// 根据ID卡获取主控记录
			string strSql = @"select t from FsGatelog as t where t.State = '0' and t.CardUid = :CardUid";
			FsGatelog gateLog = Session.CreateQuery(strSql).
				SetString("CardUid", CardUid).UniqueResult<FsGatelog>();
			return gateLog;
		}

		/// <summary>
		/// 根据ID卡和道闸返回一个合法的通行控制记录
		/// 对于无控制记录的
		/// </summary>
		/// <param name="CardUid"></param>
		/// <param name="GateId"></param>
		/// <returns></returns>
		public FsGatelog GetCurGateLogByIdCard(string CardUid, string CarNo, string GateId)
		{
			// 读取ID卡信息
			InfraIdcard idCardInfo = new InfraIdcardRepositoryImpl().GetByCardUId(CardUid);
			if (idCardInfo == null)
			{
				throw new ValidationException("未知的ID卡信息.");
			}

			// 读取当前道闸信息
			FsGateinfo gateInfo = new FsGateinfoRepositoryImpl().Get(GateId);
			if (gateInfo == null)
			{
				throw new ValidationException("未知的道闸信息.");
			}

			// 根据ID卡获取主控记录
			FsGatelog gateLog = this.GetCurrentLogByIdCard(CardUid);

			switch (idCardInfo.Type)
			{
				case InfraIdcardType.CarInfoCard:
					// 商品车信息卡
					if (gateLog == null)
						throw new ValidationException("商品车未审批提车不可通行。"); //无通行控制记录
					FsCarbaseinfo carInfo = new FsCarbaseinfoRepositoryImpl().GetByQuery(idCardInfo.CardUid);
					// 判断车辆信息
					if (CarNo != carInfo.FrameId) //车架号是否一致
						throw new ValidationException("商品车信息不符,车架号不一致。");
					break;
				case InfraIdcardType.OffiCarCard:
					// 公务车
					if(gateLog == null)
						throw new ValidationException("公务车未审批提车不可通行。");
					FsIntlVehicle intlVehicle = new FsIntlVehicleRepositoryImpl().GetByCardUid(idCardInfo.CardUid);
					// 判断车辆信息
					if (CarNo != intlVehicle.CarNo)
						throw new ValidationException("公务车信息不符,车牌号不一致。");
					break;
				case InfraIdcardType.PersonCarCard:
					//员工车辆
					if (gateLog == null)
					{
						// 该车辆第一次通过道闸
						gateLog = new FsGatelog
						{
							CardUid = CardUid,
							State = "0", //活动标志
							EntTime = System.DateTime.Now,
							InfraIdcard = idCardInfo,
							Type = idCardInfo.Type,
							GateLogList = new HashedSet<FsGatelogList>()
						};
					}
					FsIntlVehicle persVehicle = new FsIntlVehicleRepositoryImpl().GetByCardUid(idCardInfo.CardUid);
					// 判断车辆信息
					if (CarNo != persVehicle.CarNo)
						throw new ValidationException("员工车辆信息不符,车牌号不一致。");
					break;
				case InfraIdcardType.TempGateCard:
					//临时卡
					if (gateLog == null)
					{
						if (gateInfo.OutArea.Code != "00000")
						{
							// 已出场的卡必须从进场道闸入场
							throw new ValidationException("此临时卡已出场。不可通过道闸[" + gateInfo.Name + "]");
						}
						else
						{
							gateLog = new FsGatelog
							{
								CardUid = CardUid,
								State = "0", //活动标志
								CarNo = CarNo,	//登记入场的车牌号
								EntTime = System.DateTime.Now,
								InfraIdcard = idCardInfo,
								Type = idCardInfo.Type,
								IoControlFlag = "I", //指定临时卡只能是进场
								GateLogList = new HashedSet<FsGatelogList>()
							};
						}
					}
					else
					{
						if (CarNo != gateLog.CarNo)
							throw new ValidationException("该临时卡的车辆信息与系统登记不一致。");
					}
					break;
				default:
					//无效卡
					throw new ValidationException("无效的通行卡类型.");
			}
			gateLog.IoControlFlag = this.GetIoControlFlag(gateInfo, gateLog);
			gateLog.CurrentGate = gateInfo;
			return gateLog;
		}

		/// <summary>
		/// 通过ID卡获取ID状态
		/// </summary>
		/// <param name="CardUId"></param>
		/// <returns></returns>
		public FsGateIDCard GetIdCardState(string CardUId)
		{
			InfraIdcardRepositoryImpl idCardRep = new InfraIdcardRepositoryImpl();
			// 读取ID卡信息
			FsGateIDCard idCardInfo = (FsGateIDCard)idCardRep.Load(CardUId);
			// 读取最近通行日志
			idCardInfo.LatestMainLog = this.GetLatestMainGateLogByCardUid(CardUId);
			// 读取最近的闸机记录
			idCardInfo.LatestGateLog = this.GetLatestGateLogByCardUid(CardUId);
			// 返回
			return idCardInfo;
		}

		/// <summary>
		/// 根据ID卡号查询未结束的出入记录
		/// </summary>
		/// <param name="CardUid"></param>
		/// <returns></returns>
		public FsGatelog GetLatestMainGateLogByCardUid(string CardUid)
		{
			string strSql = @"select t from FsGatelog as t where t.State = '0' and t.CardUid = :CardUid";
			return Session.CreateQuery(strSql).SetString("CardUid", CardUid).UniqueResult<FsGatelog>();
		}

		/// <summary>
		/// 根据ID卡号查询最近的通过道闸的记录
		/// </summary>
		/// <param name="CardUid"></param>
		/// <returns></returns>
		public FsGatelogList GetLatestGateLogByCardUid(string CardUid)
		{
			string strSql = @"select t from FsGatelogList as t 
					where t.FsGatelog.CardUid = :CardUid
					order by t.CreateTime desc";
			return Session.CreateQuery(strSql).SetString("CardUid", CardUid)
				.SetMaxResults(1).UniqueResult<FsGatelogList>();
		}
	}
}
